package com.lyx.rpc.serialization.jdk;

import com.lyx.rpc.common.exception.SerializerException;
import com.lyx.rpc.serialization.api.Serialization;
import com.lyx.rpc.spi.annotation.SPIClass;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;

/**
 * @Author by lyx
 * jdk序列化
 */
@SPIClass
public class JdkSerialization implements Serialization {
    private final Logger logger = LoggerFactory.getLogger(JdkSerialization.class);
    /**
     * ai:
     * 在try语句块中，使用try-with-resources语句自动管理资源的关闭。创建一个ByteArrayOutputStream用于存储序列化后的字节数组，以及一个ObjectOutputStream用于将对象写入到字节流中。
     * 通过objectOutputStream.writeObject(obj)将传入的对象写入到ObjectOutputStream中，实际上就是进行序列化操作，将对象转换为字节流并写入到ByteArrayOutputStream中。
     * 最后，通过byteArrayOutputStream.toByteArray()获取ByteArrayOutputStream中的字节数组并返回，这个字节数组就是序列化后的结果。
     *
     * @param obj
     * @param <T>
     * @return
     */
    @Override
    public <T> byte[] serialize(T obj) {
        logger.info("execute jdk serialize...");
        if (obj == null) {
            throw new SerializerException("JdkSerialization#serialize-序列化对象为空！");
        }
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
             ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream)) {
            objectOutputStream.writeObject(obj);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new SerializerException(e.getMessage(), e);
        }
    }

    /**
     * ai:
     *      在这段代码中，cls参数看起来似乎没有被直接使用，但实际上它在反序列化过程中是被隐式使用的。
     *      在调用in.readObject()之后，进行了强制类型转换return (T) in.readObject();。这个强制类型转换是基于期望的返回类型Class<T> cls来进行的。
     *       如果没有这个参数，编译器无法确定反序列化后的对象应该被转换为什么具体的类型。
     *       虽然在代码中没有直接通过cls的方法或属性来操作，但它为类型转换提供了必要的类型信息，确保反序列化的结果可以正确地转换为期望的类型T。
     * @param data
     * @param cls
     * @return
     * @param <T>
     */
    @Override
    public <T> T deserialize(byte[] data, Class<T> cls) {
        logger.info("execute jdk deserialize...");
        if (data == null) {
            throw new SerializerException("JdkSerialization#deserialize-反序列化对象为空！");
        }
        try (ByteArrayInputStream is = new ByteArrayInputStream(data);
             ObjectInputStream in = new ObjectInputStream(is)) {
            return (T) in.readObject();
        } catch (Exception e) {
            throw new SerializerException(e.getMessage(), e);
        }
    }
}
